package com.changgou.seckill.task;

import com.changgou.entity.SeckillStatus;
import com.changgou.seckill.dao.SeckillGoodsMapper;
import com.changgou.seckill.pojo.SeckillGoods;
import com.changgou.seckill.pojo.SeckillOrder;
import com.changgou.util.IdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * 多线程下单实现
 *
 * @author 戴金华
 * @date 2019-12-30 11:24
 */
@Component
public class MultiThreadingCreateOrder {


    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IdWorker idWorker;

    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    /**
     * 异步创建秒杀订单
     *
     * @Async:该方法会异步执行(底层多线程方式)
     */
    @Async
    public void createOrder() {
        try {
            System.out.println(Thread.currentThread().getName() + "睡一会再下单");
            Thread.sleep(10000);

            //从队列中获取用户排队信息
            SeckillStatus seckillStatus = (SeckillStatus) redisTemplate.boundListOps("SeckillOrderQueue").rightPop();
            if (seckillStatus == null) {
                //如果队列中没有信息
                return;
            }
            String time = seckillStatus.getTime();
            String username = seckillStatus.getUsername();
            Long id = seckillStatus.getGoodsId();

            /**
             * 解决超卖问题
             * 先到SeckillGoodsCountList_id队列中获取该商品的一个信息 如果能获取 则可以下单
             * 如果不能获取该商品的队列信息 表示没有库存 清理排队信息
             */
            Object secObj = redisTemplate.boundListOps("SeckillGoodsQueue_" + seckillStatus.getGoodsId()).rightPop();
            if (secObj == null) {
                //无法获取队列信息 清理排队信息
                clearQueue(username);
            }


            //获取秒杀商品信息
            SeckillGoods seckillGoods = (SeckillGoods) redisTemplate.boundHashOps(PushGoodsToRedis.SECKILL_GOODS_KEY + time).get(id);

            //判断是否还存在商品
            if (seckillGoods == null) {
                throw new RuntimeException("商品已售罄");
            }

            //粉装订单信息
            SeckillOrder seckillOrder = new SeckillOrder();
            seckillOrder.setId(idWorker.nextId());  //id
            seckillOrder.setSeckillId(id);          //秒杀商品id
            seckillOrder.setUserId(username);       //用户
            seckillOrder.setCreateTime(new Date()); //创建时间
            seckillOrder.setStatus("0");            //未支付

            /**
             * 存储订单对象
             * 一个用户只能下一个订单
             *
             */
            redisTemplate.boundHashOps("SeckillOrder").put(username, seckillOrder);


            /**
             * 库存递减
             *      如果是最后一个库存 则 删除redis并且同步到数据库
             */
            seckillGoods.setStockCount(seckillGoods.getStockCount() - 1);

            //获取SeckillGoodsCountList_id队列的长度
            Long size = redisTemplate.boundListOps("SeckillGoodsQueue_" + id).size();
//            if (seckillGoods.getStockCount() <= 0) {
            if (size<=0){

                //同步数量
                seckillGoods.setStockCount(size.intValue());
                //同步到数据库
                seckillGoodsMapper.updateByPrimaryKeySelective(seckillGoods);

                //如果当前库存是最后一个库存
                redisTemplate.boundHashOps(PushGoodsToRedis.SECKILL_GOODS_KEY + time).delete(id);

            } else {
                redisTemplate.boundHashOps(PushGoodsToRedis.SECKILL_GOODS_KEY + time).put(id, seckillGoods);
            }

            //更新抢单状态
            seckillStatus.setOrderId(seckillOrder.getId());
            seckillStatus.setStatus(2);
            redisTemplate.boundHashOps("UserQueueStatus").put(username, seckillStatus);

            System.out.println(Thread.currentThread().getName() + "订单完成");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清理用户排队信息
     * @param username
     */
    public void clearQueue(String username){
        //用户排队表示
        redisTemplate.boundHashOps("UserQueueCount").delete(username);
        //用户排队对象
        redisTemplate.boundHashOps("UserQueueStatus").delete(username);
    }
}
